﻿@inject IJSRuntime JsRuntime;
@inject MaterialIssueSerivce MaterialService;
@inject SysConfigService ConfigService;
@implements IDisposable
@using System.IO.Ports;
@using System.Text;
@using Newtonsoft.Json;
@using Newtonsoft.Json.Linq
@using Rmac.Service.Config;
@using Rmac.Uitls;

@code {
    private static Action<string> _beginSerialPortAction;
    private static Action _closeSerialPortAction;
    private static Action<int> _guilingOrQuPiAction;
    private static Func<MaterialIssue, Task<List<MaterialIssue>>> _issueGetListFun;
    private static Func<MaterialIssue, Task<object>> _issueInsertFun;
    private static Func<MaterialIssue, Task<object>> _issueDeleteFun;
    private static Func<MaterialIssueChildBatch, Task<object>> _issueChildBatchInsertFun;
    private static Func<MaterialIssueChild, Task<object>> _issueChildInsertFun;
    private static Func<MaterialIssueChild, Task<object>> _issueChildUpdatePlanQtyFun;
    private static Func<MaterialIssueChild, Task<object>> _issueChildUpdateStatusFun;
    private static Func<MaterialIssue, Task<object>> _issueUpdateStatusFun;
    private static Func<MaterialIssue, Task<string>> _getIssueFinishDetailFun;
    private static Func<string, Task<SysConfig>> _getConfigByCodeFun;



    private static readonly SerialPort ComDevice = new();
    readonly byte[] _uartRBuf = new byte[30];
    int _pUartRbufW ;
    private string Weight { set; get; }
    //static int _isSendWeight = 1;

    protected async override void OnInitialized()
    {
        _beginSerialPortAction = InitPort;
        _closeSerialPortAction = ClosePort;
        _guilingOrQuPiAction = GuiLingOrQuPi;
        _issueGetListFun = MaterialService.QueryIssueList;
        _issueInsertFun = MaterialService.ScanQrCodeSaveIssue;
        _issueDeleteFun = MaterialService.DeleteIssue;
        _issueChildBatchInsertFun = MaterialService.InsertIssueChildBatch;
        _issueChildInsertFun = MaterialService.InsertIssueChildOutInv;
        _issueChildUpdatePlanQtyFun = MaterialService.UpdateIssueChildPlanQty;
        _issueChildUpdateStatusFun = MaterialService.UpdateIssueChildStatus;
        _issueUpdateStatusFun = MaterialService.UpdateIssueStatus;
        _getIssueFinishDetailFun = MaterialService.GetIssueFinshDetail;
        _getConfigByCodeFun = ConfigService.GetConfigByCode;

        var config = await _getConfigByCodeFun.Invoke("DZCKC");
    }

    [JSInvokable]
    public  static async Task<string> BeginReadWeight()
    {
        var config = await _getConfigByCodeFun.Invoke("DZCKC");
        _beginSerialPortAction.Invoke(config.Value);
        return await Task.FromResult("开始读取数据" + JsonConvert.SerializeObject(SerialPort.GetPortNames()));
    }

    [JSInvokable]
    public  static async Task<string> EndReadWeight()
    {
        _closeSerialPortAction.Invoke();
        return await Task.FromResult("停止读取数据");
    }
    [JSInvokable]
    public  static async Task<string> GuiLingWeight(int type)
    {
        _guilingOrQuPiAction.Invoke(type);
        return await Task.FromResult(type == 1 ? "归零" : "去皮" );
    }


    [JSInvokable]
    public  static async Task<List<MaterialIssue>> GetIssueList(string jsonString)
    {
        var issue = JsonConvert.DeserializeObject<MaterialIssue>(jsonString) ?? new MaterialIssue();
        var list = await _issueGetListFun.Invoke(issue);
        return list;
    }

    [JSInvokable]
    public static async Task<object> ScanQrCodeSaveIssue(string jsonString)
    {
        if (string.IsNullOrEmpty(jsonString))
        {
            throw new Exception("工单二维码不能为空");
        }
        jsonString = StringUtils.Decompress(jsonString);
        var list = JsonConvert.DeserializeObject<List<List<object>>>(jsonString);
        var first = list.First();
        var issue = new MaterialIssue()
            {
                NO = first[0].ToString(),
                InventoryID = first[1].ToString(),
                ProjectBatch = first[2].ToString(),
                DeskStock = first[3].ToString(),
                EviType = first[4].ToString(),
                Status = "5",
                Date = DateTime.Now,
                FG_InvChild = new List<MaterialIssueChild>()
            };

        foreach (var child in from JArray item in list[1] let status = item[10] select new MaterialIssueChild
        {
            Noid = Convert.ToInt32(item[0].ToString()),
            RountNo = Convert.ToInt32(item[1].ToString()),
            InventoryID = item[2].ToString(),
            InventoryDesc = item[3].ToString(),
            PlanQty = Convert.ToDouble(item[4].ToString()),
            ActQty = Convert.ToDouble(item[5].ToString()),
            Tolerance = Convert.ToDouble(item[6].ToString()),
            ProjectBatch = item[7].ToString(),
            Scale = item[8].ToString(),
            Combination = item[9] == null ? "A" : item[9].ToString(),
            Status = Convert.ToInt32(item[10] == null ? 1 : item[10].ToString()),
            IsBomOutInv = BomInvInOrOut.In,
            TopLimit = Convert.ToDouble(item[12].ToString()),
            LowerLimit = Convert.ToDouble(item[11].ToString())
        })
        {
            issue.FG_InvChild.Add(child);
        }
        return await _issueInsertFun.Invoke(issue);
    }

    [JSInvokable]
    public static async Task<object> DeleteIssue(string jsonString)
    {
        var issue = JsonConvert.DeserializeObject<MaterialIssue>(jsonString);
        if (issue is null || issue.Id == 0)
        {
            throw new Exception("工单ID参数不能为空或者为0");
        }
        return await _issueDeleteFun.Invoke(issue);
    }

    [JSInvokable]
    public static async Task<object> InsertIssueChildBatch(string jsonString)
    {
        if (string.IsNullOrEmpty(jsonString))
        {
            throw new Exception("插入参数不能为空");
        }
        var issue = JsonConvert.DeserializeObject<MaterialIssueChildBatch>(jsonString);
        if (issue is null || issue.Pid == 0)
        {
            throw new Exception("工单ID参数不能为空或者为0");
        }

        return await _issueChildBatchInsertFun.Invoke(issue);
    }

    #region 插入明细配方外材料记录

    /// <summary>
    /// 插入明细配方外材料记录
    /// </summary>
    /// <param name="jsonString"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    [JSInvokable]
    public static async Task<object> InsertIssueChild(string jsonString)
    {
        if (string.IsNullOrEmpty(jsonString))
        {
            throw new Exception("插入参数不能为空");
        }
        var issue = JsonConvert.DeserializeObject<MaterialIssueChild>(jsonString);
        if (issue is null || issue.Pid == 0)
        {
            throw new Exception("工单ID参数不能为空或者为0");
        }

        return await _issueChildInsertFun.Invoke(issue);
    }

    #endregion

    #region 更新工单明细物料中的计划量

    /// <summary>
    /// 更新工单明细物料中的计划量
    /// </summary>
    /// <param name="jsonString"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    [JSInvokable]
    public static async Task<object> UpdateIssueChildPlanQty(string jsonString)
    {
        if (string.IsNullOrEmpty(jsonString))
        {
            throw new Exception("插入参数不能为空");
        }
        var issue = JsonConvert.DeserializeObject<MaterialIssueChild>(jsonString);
        if (issue is null || issue.Id == 0)
        {
            throw new Exception("ID参数不能为空或者为0");
        }

        return await _issueChildUpdatePlanQtyFun.Invoke(issue);
    }

    #endregion

    #region 更新工单明细物料中的计划量

    /// <summary>
    /// 更新工单明细物料中的计划量
    /// </summary>
    /// <param name="jsonString"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    [JSInvokable]
    public static async Task<object> UpdateIssueChildStatus(string jsonString)
    {
        if (string.IsNullOrEmpty(jsonString))
        {
            throw new Exception("插入参数不能为空");
        }
        var issue = JsonConvert.DeserializeObject<MaterialIssueChild>(jsonString);
        if (issue is null || issue.Id == 0)
        {
            throw new Exception("ID参数不能为空或者为0");
        }

        return await _issueChildUpdateStatusFun.Invoke(issue);
    }

    #endregion

    #region 更新工单状态

    /// <summary>
    /// 更新工单状态
    /// </summary>
    /// <param name="jsonString"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    [JSInvokable]
    public static async Task<object> UpdateIssueStatus(string jsonString)
    {
        if (string.IsNullOrEmpty(jsonString))
        {
            throw new Exception("插入参数不能为空");
        }
        var issue = JsonConvert.DeserializeObject<MaterialIssue>(jsonString);
        if (issue is null || issue.Id == 0)
        {
            throw new Exception("ID参数不能为空或者为0");
        }

        return await _issueUpdateStatusFun.Invoke(issue);
    }

    #endregion

    #region 导出打印完工工单数据二维码
    /// <summary>
    /// 导出打印完工工单数据二维码
    /// </summary>
    /// <param name="jsonString"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    [JSInvokable]
    public static async Task<object> PrintIssueFinishQr(string jsonString)
    {
        if (string.IsNullOrEmpty(jsonString))
        {
            throw new Exception("插入参数不能为空");
        }
        var issue = JsonConvert.DeserializeObject<MaterialIssue>(jsonString);
        if (issue is null || issue.Id == 0)
        {
            throw new Exception("ID参数不能为空或者为0");
        }
        var printContent = await _getIssueFinishDetailFun.Invoke(issue);
        new PrintUtils(printContent).PrintDocument();
        return "打印完成！";
    }

    #endregion

    private void InitPort(string prot)
    {
        ComDevice.DataReceived += Com_DataReceived;
        if (ComDevice.IsOpen == false)
        {
            ComDevice.PortName = prot;
            ComDevice.BaudRate = Convert.ToInt32(9600);
            ComDevice.Parity = Parity.None;
            ComDevice.DataBits = 8;
            ComDevice.StopBits = StopBits.One;
            ComDevice.Open();
        }
    }

    private async void Com_DataReceived(object sender, SerialDataReceivedEventArgs e) //读到数据
    {
        try
        {
            var reDatas = new byte[ComDevice.BytesToRead];
            ComDevice.Read(reDatas, 0, reDatas.Length);//读取数据
            foreach (var t in reDatas)
            {
                if (t == 0x2) _pUartRbufW = 0;
                else if ((t == '\n') || (t == 0x3))   //读到结束符就处理
                {
                    if (_uartRBuf[_pUartRbufW - 1] == '\r') _pUartRbufW -= 1;
                    Weight = Encoding.ASCII.GetString(_uartRBuf, 6, _pUartRbufW);
                    _pUartRbufW = 0;
                }
                else _uartRBuf[_pUartRbufW++] = t;
            }
            if (Weight is null) return;
            var weight2 = Weight[..Weight.LastIndexOf("\r", StringComparison.Ordinal)].Replace("kg", "").Trim();
            await JsRuntime.InvokeVoidAsync(identifier: "readWeight", weight2);
        }
        catch (Exception)
        {

            throw;
        }
        
    }
    
    #region 发送指令到电子秤

    /// <summary>
    /// 发送指令到电子秤
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    private static void SendData(byte[] data)
    {
        if (!ComDevice.IsOpen) throw new Exception("串口未打开");
        ComDevice.Write(data, 0, data.Length);//发送数据
    }
    #endregion


    #region 归零/去皮

    /// <summary>
    /// 归零/去皮
    /// </summary>
    /// <param name="type">1:归零  2：去皮</param>
    private static void GuiLingOrQuPi(int type)
    {
        switch (type)
        {
            case 1:
                SendData(Encoding.ASCII.GetBytes("SZ\r\n"));
                break;
            case 2:
                SendData(Encoding.ASCII.GetBytes("ST\r\n"));
                break;
        }
        
    }

    #endregion

    private void ClosePort()
    {
        ComDevice.DataReceived -= Com_DataReceived;//绑定事件
        ComDevice.Close();
    }

    public void Dispose()
    {

    }
}